iT邦幫忙

2024 iThome 鐵人賽

DAY 11
0
Software Development

一起看無間道學EdgeDB系列 第 11

[Day11] - 初始schema:時

  • 分享至 

  • xImage
  •  

Scalar types

DayOfWeek

DayOfWeek代表一星期內七天。

scalar type DayOfWeek extending enum<Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday>;

FuzzyYear

FuzzyYear直接extending int64

scalar type FuzzyYear extending int64;

FuzzyMonth

FuzzyMonth extending int64後,再加上一個constraint,限制其值只能為1~12(註1)。

scalar type FuzzyMonth extending int64 {
    constraint expression on (__subject__ >=1 and __subject__ <=12)
}

其中__subject__代表自身,有點self或是this的味道,可以透過expression來寫出表達式。

FuzzyDay

FuzzyDay extending int64後,再加上一個constraint,限制其值只能為1~31。

scalar type FuzzyDay extending int64 {
    constraint expression on (__subject__ >=1 and __subject__ <=31)
}

FuzzyHour

FuzzyHour extending int64後,再加上一個constraint,限制其值只能為0~23。

scalar type FuzzyHour extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=23)
}

FuzzyMinute

FuzzyMinute extending int64後,再加上一個constraint,限制其值只能為0~59。

scalar type FuzzyMinute extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=59)
}

FuzzySecond

FuzzySecond extending int64後,再加上一個constraint,限制其值只能為0~59。

scalar type FuzzySecond extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=59)
}

Object types

FuzzyTime

FuzzyTime除了包含前述七個scalar typeproperty外,還加了一個fuzzy_fmt roperty,一個trigger及一個constraint

type FuzzyTime {
    fuzzy_year: FuzzyYear;
    fuzzy_month: FuzzyMonth;
    fuzzy_day: FuzzyDay;
    fuzzy_hour: FuzzyHour;
    fuzzy_minute: FuzzyMinute;
    fuzzy_second: FuzzySecond;
    fuzzy_dow: DayOfWeek; 
    fuzzy_fmt:= (
        with Y:= <str>.fuzzy_year ?? "YYYY",
             m:= <str>.fuzzy_month ?? "MM",
             m:= m if len(m) > 1 else "0" ++ m,
             d:= <str>.fuzzy_day ?? "DD",
             d:= d if len(d) > 1 else "0" ++ d,
             H:= <str>.fuzzy_hour ?? "HH24",
             H:= H if len(H) > 1 else "0" ++ H,
             M:= <str>.fuzzy_minute ?? "MI",
             M:= M if len(M) > 1 else "0" ++ M,
             S:= <str>.fuzzy_second ?? "SS",
             S:= S if len(S) > 1 else "0" ++ S,
             dow:= <str>.fuzzy_dow ?? "ID", 
        select Y ++ "/" ++ m ++ "/" ++ d ++ "_" ++
               H ++ ":" ++ M ++ ":" ++ S ++ "_" ++
               dow       
    );

    trigger fuzzy_month_day_check after insert, update for each 
    when (exists __new__.fuzzy_month and exists __new__.fuzzy_day) 
    do ( 
        assert_exists(
            cal::to_local_date(
                __new__.fuzzy_year ?? 2002, 
                __new__.fuzzy_month,
                __new__.fuzzy_day
            )
        ) 
    );
    constraint exclusive on (.fuzzy_fmt);
}

fuzzy_fmt

fuzzy_fmtcomputed property,為一特殊的str格式來表達每個FuzzyTime object。其中??是指當該scalar type為空的set時(即<str>{}),所給予的預設值

trigger

當同時給定fuzzy_monthfuzzy_day時,我們可以透過cal::to_local_date來驗證這樣的月份與日期,是否為一有效的組合。

逐步拆解各部份語法:

  • fuzzy_month_day_check為此trigger名字,可自行定義。afterfor each中間,輸入想要trigger的類型。本例中是想要當對FuzzyTime進行insertupdate時,才會觸發trigger

    trigger fuzzy_month_day_check after insert, update for each
    
  • when為選擇性條件,當其後expressiontrue時,才會觸發trigger。其中__new__是指我們想要insertupdateobject

    when (exists __new__.fuzzy_month and exists __new__.fuzzy_day) 
    
  • do為這個trigger想要執行的內容。我們這裡使用assert_exists搭配cal::to_local_date來驗證給定的月份及日期組合是否合理。當沒有給定年份時,使用??語法指定為無間道主要劇情時間的2002年。由於我們的fuzzy_day已經被FuzzyDay限制在1~31之間,所以這個trigger可以幫我們去除掉2/302/314/316/319/3111/31等不合理的時間,至於沒有給定年份的2/29是無法生成的(因為2002年不是閏年)。如果真的要生成2/29這麼特別的日子,需強制加上年份來鑒別其是否為一合理的時間。

    do ( 
        assert_exists(
            cal::to_local_date(
                __new__.fuzzy_year ?? 2002, 
                __new__.fuzzy_month, 
                __new__.fuzzy_day
            )
        ) 
    );
    

另外,當您使用略為超過合理時間的日期(如4/31),cal::to_local_date報錯訊息會和一般情況不太一樣,會貼心地提示您這個日期剛好超出合理區間。

例如,使用4/31會報錯如下:

edgedb error: InvalidValueError: cal::local_date field value out of range: 2002-04-31

4/40則會報錯如下:

edgedb error: ConstraintViolationError: invalid FuzzyDay
Detail: invalid scalar type 'default::FuzzyDay'

constraint

針對fuzzy_fmt property加上exclusive後,可以確保當使用FuzzyTime時,不會生成一個以上可以表達同一模糊時間的FuzzyTime object

備註

註1: EdgeDB內建了許多好用的constraint,可以節省大家寫constraint exression on的功夫。例如這邊我們可以搭配使用min_value()max_value()兩個constraint來取代expression

參考資料

無間EdgeDB初始schema:時


上一篇
[Day10] - 初始schema:人
下一篇
[Day12] - 初始schema:地
系列文
一起看無間道學EdgeDB30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言